<template>
    <div>
        <el-form ref="form" label-width="80px" :model="spu">
            <el-form-item label="SPU名称">
                <el-input
                    placeholder="SPU名称"
                    v-model="spu.spuName"
                ></el-input>
            </el-form-item>
            <el-form-item label="品牌">
                <el-select placeholder="请选择品牌" v-model="spu.tmId">
                    <el-option
                        v-for="(tradeMark, index) in spuTradeMarkList"
                        :key="tradeMark.id"
                        :value="tradeMark.id"
                        :label="tradeMark.tmName"
                    >
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="SPU描述">
                <el-input
                    type="textarea"
                    placeholder="SPU描述"
                    rows="4"
                    v-model="spu.description"
                ></el-input>
            </el-form-item>
            <!-- 照片墙 -->
            <el-form-item label="SPU图片">
                <!-- 
                    上传图片
                    action：图片上传的地址
                    list-type: 文件列表的类型 on-preview:图片预览 on-remove:当删除图片的时候触发
                    file-list 照片墙需要展示的数据(array 数组里面必须要有name url 属性)
                 -->
                <el-upload
                    action="/dev-api/admin/product/fileUpload"
                    list-type="picture-card"
                    :on-preview="handlePictureCardPreview"
                    :on-remove="handleRemove"
                    :file-list="spuImagesList"
                    :on-success="handleSuccess"
                >
                    <i class="el-icon-plus"></i>
                </el-upload>
                <el-dialog :visible.sync="dialogVisible">
                    <img width="100%" :src="dialogImageUrl" alt="" />
                </el-dialog>
            </el-form-item>
            <el-form-item label="销售属性">
                <el-select
                    :placeholder="`还有${unSelectSaleAttr.length}个未选择`"
                    v-model="attrIdAndAttrName"
                >
                    <el-option
                        v-for="unSelect in unSelectSaleAttr"
                        :key="unSelect.id"
                        :label="unSelect.name"
                        :value="`${unSelect.id}:${unSelect.name}`"
                    >
                    </el-option>
                </el-select>
                <el-button
                    type="primary"
                    icon="el-icon-plus"
                    :disabled="!attrIdAndAttrName"
                    @click="addSaleAttr"
                    >添加销售属性</el-button
                >
                <!-- 展示当前spu属于自己的销售属性 -->
                <el-table
                    style="width: 100%"
                    border
                    :data="spu.spuSaleAttrList"
                >
                    <el-table-column
                        type="index"
                        label="序号"
                        width="80"
                        align="center"
                    >
                    </el-table-column>
                    <el-table-column
                        prop="saleAttrName"
                        label="属性名"
                        width="width"
                    >
                    </el-table-column>
                    <el-table-column label="属性值名称列表" width="width">
                        <template #default="{ row, $index }">
                            <el-tag
                                :key="tag.id"
                                v-for="tag in row.spuSaleAttrValueList"
                                closable
                                :disable-transitions="false"
                                @close="handleClose(tag, row)"
                            >
                                {{ tag.saleAttrValueName }}
                            </el-tag>
                            <!-- 底下的结构可以当做之前做过的span和input的切换 -->
                            <el-input
                                class="input-new-tag"
                                v-if="row.inputVisible"
                                v-model="row.inputValue"
                                ref="saveTagInput"
                                size="small"
                                @blur="handleInputConfirm(row)"
                                @keyup.enter.native="handleInputConfirm"
                            >
                            </el-input>
                            <!--  @click="showInput" -->
                            <el-button
                                v-else
                                class="button-new-tag"
                                size="small"
                                @click="addSaleAttrValue(row, $index)"
                                >添加</el-button
                            >
                        </template>
                    </el-table-column>
                    <el-table-column prop="prop" label="操作" width="width">
                        <template #default="{ row, $index }">
                            <el-button
                                type="danger"
                                icon="el-icon-delete"
                                size="mini"
                                @click="deleteSaleAttr($index)"
                            ></el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="addOrUpdateSpu"
                    >保存</el-button
                >
                <el-button @click="cancel">取消</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
export default {
    name: "SpuForm",
    data() {
        return {
            dialogImageUrl: "",
            dialogVisible: false,
            // 存储spu信息属性
            // spu属性初始化的时候是一个空的对象，在修改spu的时候，会向服务器发请求，返回spu对象，在修改的时候可以利用它修改最新的数据
            // 添加spu,如果是添加spu的时候，并没有向服务器发请求，数据应该如何处理呢？查看文档初始化参数
            spu: {
                category3Id: 0, // 三级分类的id
                description: "", // 描述
                spuName: "", // spu的名称
                tmId: "", // 品牌的id
                // 收集spu图片的信息
                spuImageList: [
                    /* {
                        id: 0,
                        imgName: "string",
                        imgUrl: "string",
                        spuId: 0,
                    }, */
                ],
                // 平台属性与属性值的收集
                spuSaleAttrList: [
                    /* {
                        baseSaleAttrId: 0,
                        id: 0,
                        saleAttrName: "string",
                        spuId: 0,
                        spuSaleAttrValueList: [
                            {
                                baseSaleAttrId: 0,
                                id: 0,
                                isChecked: "string",
                                saleAttrName: "string",
                                saleAttrValueName: "string",
                                spuId: 0,
                            },
                        ],
                    }, */
                ],
            },
            spuTradeMarkList: [], // 存储spu品牌信息
            spuImagesList: [], // 存储spu图片
            spuSaleList: [], // 存储全平台销售属性
            tmName: "", // 品牌名称
            attrIdAndAttrName: "", // 收集未选择的id
        }
    },
    methods: {
        // 照片墙删除某一个图片时会触发
        handleRemove(file, fileList) {
            // file 代表着是你删除的图片
            // fileList 代表着是照片墙删除某一张图片之后,剩下的图片
            // console.log(file, fileList)
            // 收集照片墙图片的数据
            // 对于已有的图片(显示在照片墙中),它有服务器不需要的属性name url,因为照片墙需要这两个属性
            // 服务器是不需要这两个属性的,所以将来提交给服务器时需要去除
            this.spuImagesList = fileList
        },
        // 照片墙预览的回调
        handlePictureCardPreview(file) {
            // 将图片的地址赋值给dialogImageUrl
            this.dialogImageUrl = file.url
            // 对话框显示
            this.dialogVisible = true
        },
        // 照片墙图片上传成功的回调
        handleSuccess(response, file, fileList) {
            // 收集数据
            this.spuImagesList = fileList
        },
        // 初始化SpuForm的数据
        async initSpuData(spu) {
            // 获取spu信息
            const spuResult = await this.$API.spu.reqGetSpu(spu.id)
            if (spuResult.code == 200) {
                this.spu = spuResult.data
            }
            // 获取spu品牌的信息
            const spuTradeMarkListResult =
                await this.$API.spu.reqGetTradeMarkList()
            if (spuTradeMarkListResult.code == 200) {
                this.spuTradeMarkList = spuTradeMarkListResult.data
            }
            // 获取spu图片 reqGetSpuImageList
            const spuImagesListResult = await this.$API.spu.reqGetSpuImageList(
                spu.id
            )
            if (spuImagesListResult.code == 200) {
                let listArr = spuImagesListResult.data
                // 由于照片墙显示图片的数据需要数组，数组里面的元素需要有name与url字段
                // 需要把服务器返回的数据进行修改
                listArr.forEach((item) => {
                    item.name = item.imgName
                    item.url = item.imgUrl
                })
                // 把整理好的数据赋值给
                this.spuImagesList = listArr
            }
            // 获取平台中全部的销售属性
            const spuSaleListResult =
                await this.$API.spu.reqGetBaseSaleAttrList()
            if (spuSaleListResult.code == 200) {
                this.spuSaleList = spuSaleListResult.data
            }
        },
        // 添加新的销售属性销售属性
        addSaleAttr() {
            // 已经收集需要添加的销售属性的信息
            // 把收集到的销售属性数据进行分割，然后解构赋值
            const [baseSaleAttrId, saleAttrName] =
                this.attrIdAndAttrName.split(":")
            // 向spu对象的spuSaleAttrList属性里面添加新的销售属性
            const newSaleArr = {
                baseSaleAttrId,
                saleAttrName,
                spuSaleAttrValueList: [],
            }
            this.spu.spuSaleAttrList.push(newSaleArr)
            // 清空数据
            this.attrIdAndAttrName = ""
        },
        // 添加销售属性属性值
        addSaleAttrValue(row, index) {
            // 点击销售属性值当中的添加按钮的时候，需要展示input，通过inputVisible控制
            // 不能直接通过row来添inputVisible,这样添加的不是响应式数据
            this.$set(row, "inputVisible", true)
            // 通过响应式数据inputValue收集新增的销售属性字段
            this.$set(row, "inputValue")
        },
        // el-input失去焦点的事件
        handleInputConfirm(row) {
            // 解构出销售属性当中收集的数据
            const { baseSaleAttrId, inputValue } = row
            // 新增的销售属性值名称不能为空
            if (inputValue.trim() == "") {
                this.$message({ type: "warning", message: "属性值不能为空" })
                return
            }
            // 属性值不能重复 重复true 不重复false 也可以用some
            const result = row.spuSaleAttrValueList.every((item) => {
                return item.saleAttrValueName != inputValue
            })
            if (!result) {
                this.$message({ type: "warning", message: "属性值不能重复" })
                // 清除输入的数据
                row.inputValue = ""
                return
            }
            // 新增销售属性值
            let newSaleAttrValue = {
                baseSaleAttrId,
                saleAttrValueName: inputValue,
            }
            // 修改inputVisible为false,显示el-button
            row.inputVisible = false
            row.spuSaleAttrValueList.push(newSaleAttrValue)
        },
        // 删除销售属性值
        handleClose(tag, row) {
            // tag要删除的销售属性值对象
            // splice通过索引值选择要删除的元素，通过indexOf来获取要删除的元素的索引
            row.spuSaleAttrValueList.splice(
                row.spuSaleAttrValueList.indexOf(tag),
                1
            )
        },
        // 删除销售属性
        deleteSaleAttr(index) {
            this.spu.spuSaleAttrList.splice(index, 1)
        },
        // 保存按钮的回调
        async addOrUpdateSpu() {
            // 整理参数，需要整理照片墙的数据
            // 携带参数：对于图片，需要携带 imgName imgUrl
            this.spu.spuImageList = this.spuImagesList.map((item) => {
                return {
                    imgName: item.name,
                    imgUrl: (item.response && item.response.data) || item.url,
                }
            })
            const result = await this.$API.spu.reqAddOrUpdateSpu(this.spu)
            if (result.code == 200) {
                // 切换场景
                this.$emit("changeScene", {
                    scene: 0,
                    flag: this.spu.id ? "修改" : "添加",
                })
                this.$message({
                    type: "success",
                    message: "保存spu成功",
                })
            }
            // 清除数据
            Object.assign(this._data, this.$options.data())
        },
        // 点击添加spu按钮的时候，发请求的函数
        async addSpuData(category3Id) {
            // 添加spu的时候收集三级分类id
            this.spu.category3Id = category3Id
            // 获取spu品牌的信息
            const spuTradeMarkListResult =
                await this.$API.spu.reqGetTradeMarkList()
            if (spuTradeMarkListResult.code == 200) {
                this.spuTradeMarkList = spuTradeMarkListResult.data
            }
            // 获取平台中全部的销售属性
            const spuSaleListResult =
                await this.$API.spu.reqGetBaseSaleAttrList()
            if (spuSaleListResult.code == 200) {
                this.spuSaleList = spuSaleListResult.data
            }
        },
        // 取消按钮的回调
        cancel() {
            this.$emit("changeScene", { scene: 0, flag: "修改" })
            // 清理数据
            // 组件实例this._data ，可以操作data当中响应式数据
            // this.$options可以获取配置对象，配置对象的data函数执行，返回初始化的响应数据
            Object.assign(this._data, this.$options.data())
        },
    },
    computed: {
        // 计算出销售属性还没选择的数量
        unSelectSaleAttr() {
            // 整个平台销售属性一共三个:颜色 尺寸 版本 spuSaleList
            // 当前SPU拥有的属于自己的销售属性spu.spuSaleAttrList
            // this.spu.spuSaleAttrList.length
            let result = this.spuSaleList.filter((item) => {
                // every会返回一个布尔值
                return this.spu.spuSaleAttrList.every((element) => {
                    return item.name != element.saleAttrName
                })
            })
            return result
        },
    },
}
</script>
<style>
.el-tag + .el-tag {
    margin-left: 10px;
}
.button-new-tag {
    margin-left: 10px;
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
}
.input-new-tag {
    width: 90px;
    margin-left: 10px;
    vertical-align: bottom;
}
</style>